import * as parser from '@babel/parser';
import generate from '@babel/generator';
import traverse from '@babel/traverse';
import * as t from '@babel/types';
import {
  IPublicTypeJSExpression,
  IPublicTypeJSFunction,
  isJSExpression,
  isJSFunction,
} from '@alilc/lowcode-types';
import { CodeGeneratorError, IScope } from '../types';
import { transformExpressionLocalRef, ParseError } from './expressionParser';
import { isJSExpressionFn } from './common';

const logger: any = () => {};

function parseFunction(content: string): t.FunctionExpression | null {
  try {
    // 检查是否是异步函数
    const isAsync = content.trim().startsWith('async');

    // 如果是异步函数，需要先去掉async关键字再解析
    const contentToProcess = isAsync ? content.replace(/^async\s+/, '') : content;

    const ast = parser.parse(`(${contentToProcess});`, {
      plugins: ['jsx'],
    });

    let resultNode: t.FunctionExpression | null = null;
    traverse(ast, {
      FunctionExpression(path) {
        resultNode = path.node;
        // 如果原始内容是异步函数，设置async标志
        if (isAsync) {
          resultNode.async = true;
        }
        path.stop();
      },
    });
    return resultNode;
  } catch (e) {
    throw new ParseError(content, e);
  }
}

function transformFuncExpr2MethodMember(methodName: string, content: string): string {
  const funcNode = parseFunction(content);
  if (funcNode) {
    const targetNode = t.classMethod(
      'method',
      (methodName && t.identifier(methodName)) || funcNode.id || t.identifier('notDefineName'),
      funcNode.params,
      funcNode.body,
      undefined,
      undefined,
      undefined,
      funcNode.async || undefined,
    );

    const { code: resultCode } = generate(targetNode, { sourceMaps: false });
    return resultCode;
  }

  throw new Error('Can not find Function Statement');
}

export function getArrowFunction(content: string) {
  logger('【getArrowFunction】开始转换函数为箭头函数:', content);

  // 如果已经是箭头函数，直接返回
  const isArrowFunction = /^\s*(?:async\s+)?(\(.*?\)|[^=>()\s]+)\s*=>/s.test(content.trim());
  if (isArrowFunction) {
    logger('【getArrowFunction】函数已经是箭头函数，直接返回');
    return content;
  }

  // 检查是否是普通函数定义
  const isFunctionDefinition =
    content.trim().startsWith('function') || content.trim().startsWith('async function');
  logger('【getArrowFunction】是否是普通函数定义:', isFunctionDefinition);

  // 如果是完整的函数定义，需要先提取函数体
  if (content.trim().startsWith('function') || content.trim().startsWith('async function')) {
    logger('【getArrowFunction】函数是完整的函数定义，开始提取参数和函数体');
    // 检查是否是异步函数
    const isAsync = content.trim().startsWith('async');
    logger('【getArrowFunction】是否是异步函数:', isAsync);

    // 提取参数和函数体
    const funcRegex = isAsync
      ? /async\s+function\s*\(([^)]*)\)\s*{([\s\S]*)}/
      : /function\s*\(([^)]*)\)\s*{([\s\S]*)}/;

    const match = content.match(funcRegex);
    if (match) {
      logger('【getArrowFunction】成功匹配函数定义');
      const params = match[1].trim();
      let body = match[2].trim();
      logger('【getArrowFunction】提取的参数:', params);
      logger('【getArrowFunction】提取的函数体:', body);

      // 检查函数体是否只有一个return语句，并且返回的是对象字面量
      const returnObjectRegex = /^\s*return\s+({[\s\S]*});?\s*$/;
      const returnMatch = body.match(returnObjectRegex);

      if (returnMatch) {
        logger('【getArrowFunction】函数体返回对象字面量，使用括号包裹');
        const result = `${isAsync ? 'async ' : ''}(${params}) => (${returnMatch[1]})`;
        logger('【getArrowFunction】生成的箭头函数:', result);
        return result;
      }

      // 检查普通的return语句
      const simpleReturnRegex = /^\s*return\s+([\s\S]*?);?\s*$/;
      const simpleReturnMatch = body.match(simpleReturnRegex);

      if (simpleReturnMatch) {
        logger('【getArrowFunction】函数体只有一个return语句，使用表达式体箭头函数');
        const result = `${isAsync ? 'async ' : ''}(${params}) => ${simpleReturnMatch[1]}`;
        logger('【getArrowFunction】生成的箭头函数:', result);
        return result;
      } else {
        logger('【getArrowFunction】函数体不只有一个return语句，使用块体箭头函数');
        const result = `${isAsync ? 'async ' : ''}(${params}) => {${body}}`;
        logger('【getArrowFunction】生成的箭头函数:', result);
        return result;
      }
    }
  }

  // 检查是否是异步函数表达式
  if (content.trim().startsWith('async function')) {
    logger('【getArrowFunction】检测到异步函数表达式');

    // 尝试匹配异步函数的参数和函数体
    const asyncFuncRegex = /async\s+function\s*\(([^)]*)\)\s*{([\s\S]*)}/;
    const match = content.match(asyncFuncRegex);

    if (match) {
      logger('【getArrowFunction】成功匹配异步函数');
      const params = match[1].trim();
      const body = match[2].trim();

      // 检查函数体是否只有一个return语句
      const returnRegex = /^\s*return\s+([\s\S]*?);?\s*$/;
      const returnMatch = body.match(returnRegex);

      if (returnMatch) {
        logger('【getArrowFunction】异步函数体只有一个return语句，使用表达式体箭头函数');
        const result = `async (${params}) => ${returnMatch[1]}`;
        logger('【getArrowFunction】生成的异步箭头函数:', result);
        return result;
      } else {
        logger('【getArrowFunction】异步函数体不只有一个return语句，使用块体箭头函数');
        const result = `async (${params}) => {${body}}`;
        logger('【getArrowFunction】生成的异步箭头函数:', result);
        return result;
      }
    }
  }

  // 如果不是完整的函数定义或无法匹配，尝试使用babel解析
  try {
    logger('【getArrowFunction】尝试使用babel解析函数');

    // 检查是否包含常见的数组方法调用（map、filter、reduce、forEach等）
    const arrayMethodRegex =
      /\.(map|filter|reduce|forEach|find|some|every)\s*\(\s*function\s*\(([^)]*)\)\s*{([\s\S]*?)}\s*\)/;
    const arrayMethodMatch = content.match(arrayMethodRegex);

    if (arrayMethodMatch) {
      const methodName = arrayMethodMatch[1];
      logger(`【getArrowFunction】检测到${methodName}函数调用`);
      const params = arrayMethodMatch[2].trim();
      const body = arrayMethodMatch[3].trim();

      // 提取方法调用前的部分
      const prefix = content.substring(0, content.indexOf(arrayMethodMatch[0]));
      // 提取方法调用后的部分
      const suffix = content.substring(
        content.indexOf(arrayMethodMatch[0]) + arrayMethodMatch[0].length,
      );

      // 转换函数体为箭头函数
      const arrowFunction = `(${params}) => {${body}}`;

      // 组合完整表达式
      const result = `${prefix}.${methodName}(${arrowFunction})${suffix}`;
      logger(`【getArrowFunction】生成的完整表达式:`, result);
      return result;
    }

    // 保留原有的map专门处理逻辑作为备用（虽然上面的通用逻辑已经覆盖了）
    const mapFunctionRegex = /\.map\s*\(\s*function\s*\(([^)]*)\)\s*{([\s\S]*?)}\s*\)/;
    const mapMatch = content.match(mapFunctionRegex);

    if (mapMatch) {
      logger('【getArrowFunction】检测到map函数调用');
      const params = mapMatch[1].trim();
      const body = mapMatch[2].trim();

      // 提取map函数调用前的部分
      const prefix = content.substring(0, content.indexOf(mapMatch[0]));
      // 提取map函数调用后的部分
      const suffix = content.substring(content.indexOf(mapMatch[0]) + mapMatch[0].length);

      // 转换函数体为箭头函数
      const arrowFunction = `(${params}) => {${body}}`;

      // 组合完整表达式
      const result = `${prefix}.map(${arrowFunction})${suffix}`;
      logger('【getArrowFunction】生成的完整表达式:', result);
      return result;
    }

    const funcNode = parseFunction(content);
    if (funcNode) {
      logger('【getArrowFunction】babel解析成功，生成箭头函数');
      logger(
        '【getArrowFunction】解析的函数参数:',
        funcNode.params.map((p) => generate(p).code).join(', '),
      );
      logger('【getArrowFunction】解析的函数体:', generate(funcNode.body).code);

      const targetNode = t.arrowFunctionExpression(
        funcNode.params,
        funcNode.body,
        funcNode.async || undefined,
      );

      const { code: resultCode } = generate(targetNode, { sourceMaps: false });
      logger('【getArrowFunction】生成的箭头函数:', resultCode);
      return resultCode;
    } else {
      logger('【getArrowFunction】babel解析失败，没有找到函数节点');
    }
  } catch (e) {
    console.warn('【getArrowFunction】使用babel解析函数失败，尝试简单转换', e);

    // 如果babel解析失败，尝试简单的正则表达式转换
    // 匹配函数参数
    logger('【getArrowFunction】尝试使用简单的正则表达式转换');
    const simpleMatch = content.match(/function\s*\(([^)]*)\)/);
    if (simpleMatch) {
      logger('【getArrowFunction】成功匹配函数参数');
      const params = simpleMatch[1].trim();
      // 提取函数体，假设函数体是在第一个{和最后一个}之间
      const bodyStart = content.indexOf('{') + 1;
      const bodyEnd = content.lastIndexOf('}');
      if (bodyStart > 0 && bodyEnd > bodyStart) {
        logger('【getArrowFunction】成功提取函数体');
        const body = content.substring(bodyStart, bodyEnd).trim();
        const result = `(${params}) => {${body}}`;
        logger('【getArrowFunction】生成的箭头函数:', result);
        return result;
      } else {
        logger('【getArrowFunction】无法提取函数体');
      }
    } else {
      logger('【getArrowFunction】无法匹配函数参数');
    }
  }

  console.error('【getArrowFunction】无法转换函数为箭头函数:', content);
  // 如果所有尝试都失败，抛出错误
  throw new Error('Can not find Function Statement');
}

function getBodyStatements(content: string) {
  const funcNode = parseFunction(content);
  if (funcNode) {
    const statements: t.Statement[] = funcNode.body.body;

    const targetNode = t.program(statements, undefined, 'module', undefined);

    const { code: resultCode } = generate(targetNode, { sourceMaps: false });
    return resultCode;
  }

  throw new Error('Can not find Function Statement');
}

/**
 * 是否是广义上的 JSFunction
 * @param value
 * @returns
 */
export function isBroadJSFunction(value: unknown): boolean {
  return isJSExpressionFn(value) || isJSFunction(value);
}

export function generateExpression(
  value: any,
  scope: IScope,
  options: { preserveThisForSlotParams?: boolean } = {},
): string {
  if (isJSExpression(value)) {
    const exprVal = (value as IPublicTypeJSExpression).value.trim();
    if (!exprVal) {
      return 'null';
    }

    try {
      logger('【generateExpression】处理表达式:', exprVal);

      // 处理作用域变量，移除this.前缀
      if (scope && scope.bindings) {
        const bindings = scope.bindings.getAllBindings() || [];
        logger('【generateExpression】当前作用域变量:', bindings);

        if (bindings.length > 0) {
          // 处理作用域变量引用
          let processedExpr = exprVal;
          bindings.forEach((binding) => {
            // 如果设置了preserveThisForSlotParams为true，则保留JSSlot参数的this前缀
            if (options.preserveThisForSlotParams) {
              logger(`【generateExpression】保留JSSlot参数 ${binding} 的this前缀`);

              // 检查是否已经有this前缀
              const thisPattern = new RegExp(`\\bthis\\.${binding}\\b`, 'g');
              const standalonePattern = new RegExp(`\\b${binding}\\b(?!\\s*=)(?!\\.|\\\")`, 'g');

              // 如果表达式中有独立的binding变量（没有this前缀），则添加this前缀
              if (standalonePattern.test(processedExpr) && !thisPattern.test(processedExpr)) {
                logger(`【generateExpression】为JSSlot参数 ${binding} 添加this前缀`);
                processedExpr = processedExpr.replace(standalonePattern, `this.${binding}`);
              }

              // 处理带属性的JSSlot参数，如record.property或record?.property
              const propPattern = new RegExp(`\\b${binding}(\\??\\.\\w+)`, 'g');
              if (propPattern.test(processedExpr)) {
                // 检查是否已经有this前缀
                const thisPropPattern = new RegExp(`\\bthis\\.${binding}(\\??\\.\\w+)`, 'g');
                if (!thisPropPattern.test(processedExpr)) {
                  logger(`【generateExpression】为带属性的JSSlot参数 ${binding} 添加this前缀`);
                  processedExpr = processedExpr.replace(propPattern, `this.${binding}$1`);
                }
              }
            } else {
              // 特殊处理 this.props 的引用
              if (binding === 'props' && processedExpr.includes('this.props')) {
                logger('【generateExpression】保留 this.props 引用');
                return processedExpr;
              }

              const pattern = new RegExp(`\\bthis\\.${binding}\\b`, 'g');
              if (pattern.test(processedExpr)) {
                if (processedExpr.includes('PLATFORM_WAIT_CONFIRM_DISPATCH_NUM')) {
                  debugger;
                }
                logger(`【generateExpression】替换 this.${binding} 为 ${binding}`);
                processedExpr = processedExpr.replace(pattern, binding);
                if (processedExpr.includes('PLATFORM_WAIT_CONFIRM_DISPATCH_NUM')) {
                  debugger;
                }
              }
            }
          });

          logger('【generateExpression】处理后的表达式:', processedExpr);
          return processedExpr;
        }
      }

      // 如果没有作用域变量或处理失败，直接返回原始表达式
      return exprVal;
    } catch (e) {
      throw new CodeGeneratorError(
        `\n表达式: ${exprVal}\n转换失败: ${(e as Error).message}`,
        value,
      );
    }
  }

  throw new CodeGeneratorError('调用错误，value 不是 JSExpression 类型', value);
}

function getFunctionSource(cfg: IPublicTypeJSFunction): string {
  return cfg.source || cfg.value || cfg.compiled;
}

export function generateFunction(
  value: any,
  scope?: IScope,
  config: {
    name?: string;
    isMember?: boolean;
    isBlock?: boolean;
    isArrow?: boolean;
    isBindExpr?: boolean;
    loopItemName?: string;
    loopIndexName?: string;
  } = {
    name: undefined,
    isMember: false,
    isBlock: false,
    isArrow: false,
    isBindExpr: false,
  },
) {
  logger('【generateFunction】开始处理函数，配置:', config);

  if (isBroadJSFunction(value)) {
    const functionCfg = value as IPublicTypeJSFunction;
    let functionSource = getFunctionSource(functionCfg);

    logger('【generateFunction】原始函数源码:', functionSource);

    // 检查函数是否已经是箭头函数
    // 修复正则表达式，确保只匹配最外层的函数定义
    // 使用 ^ 确保从字符串开始匹配，避免匹配到内部的箭头函数
    const isArrowFunction = /^\s*(?:async\s+)?(\(.*?\)|[^=>()\s]+)\s*=>/s.test(
      functionSource.trim(),
    );
    logger('【generateFunction】是否已经是箭头函数:', isArrowFunction, functionSource);

    // 检查函数是否是普通函数定义
    const isRegularFunction =
      functionSource.trim().startsWith('function') ||
      functionSource.trim().startsWith('async function');
    logger('【generateFunction】是否是普通函数定义:', isRegularFunction);

    // 检查函数是否包含this引用
    const hasThisReference = functionSource.includes('this.');
    logger('【generateFunction】是否包含this引用:', hasThisReference);

    // 处理循环变量引用
    if (
      scope &&
      (config.loopItemName || config.loopIndexName || scope.bindings?.getAllBindings().length > 0)
    ) {
      logger('【generateFunction】开始处理循环变量引用');
      // 获取当前作用域中的所有绑定变量
      const bindings = scope.bindings?.getAllBindings() || [];
      logger('【generateFunction】当前作用域中的绑定变量:', bindings);

      // 处理当前循环变量
      if (config.loopItemName && functionSource.includes(`this.${config.loopItemName}`)) {
        logger(`【generateFunction】替换 this.${config.loopItemName} 为 ${config.loopItemName}`);
        functionSource = functionSource.replace(
          new RegExp(`this\\.${config.loopItemName}`, 'g'),
          config.loopItemName,
        );
      }

      if (config.loopIndexName && functionSource.includes(`this.${config.loopIndexName}`)) {
        logger(`【generateFunction】替换 this.${config.loopIndexName} 为 ${config.loopIndexName}`);
        functionSource = functionSource.replace(
          new RegExp(`this\\.${config.loopIndexName}`, 'g'),
          config.loopIndexName,
        );
      }

      // 处理所有可能的循环变量
      bindings.forEach((binding) => {
        if (
          binding !== config.loopItemName &&
          binding !== config.loopIndexName &&
          functionSource.includes(`this.${binding}`)
        ) {
          logger(`【generateFunction】替换 this.${binding} 为 ${binding}`);
          functionSource = functionSource.replace(new RegExp(`this\\.${binding}`, 'g'), binding);
        }
      });

      logger('【generateFunction】处理循环变量引用后的函数源码:', functionSource);
    }

    // 如果明确要求使用箭头函数，尝试转换
    if (config.isArrow) {
      logger('【generateFunction】明确要求使用箭头函数');

      // 如果已经是箭头函数，直接返回
      if (isArrowFunction) {
        logger('【generateFunction】函数已经是箭头函数，直接返回');
        return functionSource;
      }

      // 如果是普通函数定义，需要转换为箭头函数
      if (isRegularFunction || hasThisReference) {
        logger('【generateFunction】函数是普通函数定义或包含this引用，尝试转换为箭头函数');
        try {
          const arrowFunction = getArrowFunction(functionSource);
          logger('【generateFunction】转换为箭头函数成功:', arrowFunction);
          return arrowFunction;
        } catch (e) {
          console.warn('【generateFunction】转换为箭头函数失败，使用原始函数', e);
          return functionSource;
        }
      }

      // 如果函数不包含this引用，也不是普通函数，直接返回
      logger('【generateFunction】函数不包含this引用，也不是普通函数，直接返回');
      return functionSource;
    }

    // 如果已经是箭头函数，直接返回（但仍然需要处理循环变量引用）
    if (isArrowFunction && !config.isArrow) {
      logger('【generateFunction】函数已经是箭头函数，且不需要强制转换为箭头函数，直接返回');
      return functionSource;
    }

    // 如果函数值已经是完整的函数定义，尝试转换为箭头函数
    if (
      functionSource.trim().startsWith('function') ||
      functionSource.trim().startsWith('async function')
    ) {
      logger('【generateFunction】函数是完整的函数定义');
      // 如果明确要求使用箭头函数，尝试转换
      if (config.isArrow) {
        logger('【generateFunction】明确要求使用箭头函数，尝试转换');
        try {
          const arrowFunction = getArrowFunction(functionSource);
          logger('【generateFunction】转换为箭头函数成功:', arrowFunction);
          return arrowFunction;
        } catch (e) {
          console.warn('【generateFunction】转换为箭头函数失败，使用原始函数', e);
          return functionSource;
        }
      }
      logger('【generateFunction】不需要转换为箭头函数，直接返回原始函数');
      return functionSource;
    }

    // 优先使用箭头函数，除非明确要求使用其他形式
    if (config.isArrow || (!config.isMember && !config.isBlock && !config.isBindExpr)) {
      logger('【generateFunction】优先使用箭头函数');
      // 如果原函数不是箭头函数，尝试转换为箭头函数
      if (!functionSource.trim().startsWith('(') && !functionSource.includes('=>')) {
        logger('【generateFunction】原函数不是箭头函数，尝试转换');
        try {
          const arrowFunction = getArrowFunction(functionSource);
          logger('【generateFunction】转换为箭头函数成功:', arrowFunction);
          return arrowFunction;
        } catch (e) {
          // 如果转换失败，使用原始函数
          console.warn('【generateFunction】转换为箭头函数失败，使用原始函数', e);
        }
      }
      // 如果已经是箭头函数或转换失败，直接返回
      logger('【generateFunction】原函数已经是箭头函数或转换失败，直接返回');
      return functionSource;
    }

    if (config.isMember) {
      logger('【generateFunction】转换为成员方法');
      return transformFuncExpr2MethodMember(config.name || '', functionSource);
    }
    if (config.isBlock) {
      logger('【generateFunction】转换为代码块');
      return getBodyStatements(functionSource);
    }
    if (config.isBindExpr) {
      logger('【generateFunction】处理绑定表达式');
      // 如果明确要求使用箭头函数，优先使用箭头函数
      if (config.isArrow) {
        logger('【generateFunction】明确要求使用箭头函数，尝试转换');
        try {
          const arrowFunction = getArrowFunction(functionSource);
          logger('【generateFunction】转换为箭头函数成功:', arrowFunction);
          return arrowFunction;
        } catch (e) {
          console.warn('【generateFunction】转换为箭头函数失败，使用原始函数', e);
        }
      }

      // 处理绑定表达式，检查是否包含apply和arguments
      if (functionSource.includes('.apply(this,Array.prototype.slice.call(arguments)')) {
        logger('【generateFunction】检测到apply和arguments模式');
        // 提取函数体内容
        const match = functionSource.match(
          /function\s*\(\)\s*{\s*return\s*(.*?)\.apply\(this,Array\.prototype\.slice\.call\(arguments\)\.concat\(\[(.*?)\]\)\)\s*}/s,
        );
        if (match) {
          logger('【generateFunction】成功匹配apply模式');
          const methodCall = match[1]; // 方法调用部分
          const additionalArgs = match[2]; // 额外参数部分

          // 构建新的箭头函数，正确处理参数
          const arrowFunction = `(e) => {
  ${methodCall}.apply(this, [e].concat([${additionalArgs}]));
}`;
          logger('【generateFunction】构建的箭头函数:', arrowFunction);
          return arrowFunction;
        }
      }

      // 如果没有特殊模式匹配，使用默认处理
      logger('【generateFunction】没有特殊模式匹配，使用默认处理');
      return `function ${functionSource}`;
    }
    logger('【generateFunction】没有特殊处理，直接返回函数源码');
    return functionSource;
  }

  throw new CodeGeneratorError('调用错误，value 不是 JSFunction 类型', value);
}
